---客户端更新api
--@functino
local _ccpm = class('CcpmApi', require('framework.cls.basehandler'))

--======================================
--default params
local d = Ding
local ipairs = ipairs
local n_req = ngx.req

local VER_CACHENAME = 'ver_cache'

local ENUM_VERRET = {
    ['bin_needup'] = 1,
    ['res_needup'] = 2,
    ['param_err'] = 3
}
local DB_GAMEDEV = {
    plugins = 'ccpm_pack',
    tools = 'tools'
}
local LN = d.LN
local Logger = d.Logger
local json = require("cjson")
--======================================
--字符串bin 版本号转number
local function _fmt_binver(binver)
    local binnum = 0
    local vlist = string.split(binver, '.')
    for i = #vlist, 1, -1 do
        binnum = binnum + tonumber(vlist[i]) * 10 ^ (2 * i - 1)
    end
    return binnum
end

--查看ip是否在限制列表
local function _chk_limitip(limtcache, ip)
    local iplist = json.decode(limtcache)
    if table.indexof(iplist, ip) then
        return true
    end
    return false
end

--比对bin, res版本信息
local function _chk_ver(channel, upbin, upres)
    local cfgver = require('cfg.cfgupdate')['ver_config']
    local ret = 0
    local cfgchannel = cfgver[channel]
    if not cfgchannel then
        ret = ENUM_VERRET['param_err']
        return ret
    end

    --fmt binver
    local upnum = _fmt_binver(upbin)
    local cfgnum = _fmt_binver[cfgchannel['minbin']]
    if upnum < cfgnum then
        ret = ENUM_VERRET['bin_needup']
        return ret
    end

    --fmt resver
    upnum = tonumber(upres)
    cfgnum = tonumber(cfgchannel['minres'])
    if upnum < cfgnum then
        ret = ENUM_VERRET['res_needup']
        return ret
    end

    return ret
end

---构造函数
function _ccpm:ctor(svr, ormccpm, ormccpmfav)
    _ccpm.super.ctor(self, 'ccpm', svr)
    d.bind(self, 'base_decorator')
    self._orm_ccpm = ormccpm
    self._orm_ccpmafav = ormccpmfav
end

--[[--
ccmp工具热更新版本检查
]]
function _ccpm:post_binchk()
    local err, reqdata = self:get_body_params_()
    if err then
        self:doerror(err, 'decode error')
        return
    end
    local ok, errtip = self:_chk_xlmake_update(reqdata)
    if errtip then
        self:doerror(2, errtip)
        return
    end
    self:doret()
end

--[[--
ccpm检查plugin是否存在
]]
function _ccpm:get_chkplugin_exist()
    local reqdata = ngx.req.get_uri_args() or {}
    local ret = self._orm_ccpm:find_all_with_tbname(DB_GAMEDEV['plugins'], {name = reqdata['name']})
    Logger:dump(ret, '__>>>ret')
    if ret then
        if #ret > 0 then
            self:doret(ret)
        else
            self:doret({})
        end
    else
        self:doret({})
    end
end

--[[--
ccpm检查tool是否存在
]]
function _ccpm:get_chktool_exist()
    local reqdata = ngx.req.get_uri_args() or {}
    local ret = self._orm_ccpm:find_all_with_tbname(DB_GAMEDEV['tools'], {name = reqdata['name']})
    if ret then
        if #ret > 0 then
            self:doret(ret)
        else
            self:doret({})
        end
    else
        self:doret({})
    end
end

--[[--
ccpm添加plugin
]]
function _ccpm:post_addplugin()
    local err, reqdata = self:get_body_params_()
    if err then
        self:doerror(err, 'decode error')
        return
    end
    local retchk = self:_chk_plugin_dic(reqdata)
    if retchk then
        -- chk name
        local p_list = self._orm_ccpm:find_all_with_tbname(DB_GAMEDEV['plugins'], {name = reqdata['name']})
        if type(p_list) == 'table' then
            for _, pinfo in ipairs(p_list) do
                if pinfo['ver'] == reqdata['ver'] then
                    self:doerror(2, 'plugin exists!')
                    return
                end
            end
        end
        reqdata['uploadtime'] = ngx.time()
        local ret = self._orm_ccpm:new_insert_with_tbname(DB_GAMEDEV['plugins'], reqdata)
        if ret then
            self:doret(0)
        else
            self:doerror(1, 'inser failed')
        end
    else
        self:doerror(1, 'insert info fmt not right')
    end
end

--[[
ccpm 删除远端的plugin
]]
function _ccpm:post_deleplugin()
    local err, reqdata = self:get_body_params_()
    if err then
        self:doerror(err, 'decode error')
        return
    end
    local p_tar =
        self._orm_ccpm:find_all_with_tbname(DB_GAMEDEV['plugins'], {name = reqdata['name'], ver = reqdata['ver']})
    if p_tar then
        if reqdata['usrtype'] == 1 and (reqdata['usr'] == p_tar['gitee_usr']) then
            local ret =
                self._orm_ccpm:dele_one_with_tbname(
                DB_GAMEDEV['plugins'],
                {name = reqdata['name'], ver = reqdata['ver']}
            )
            if ret then
                return self:doret(0)
            end
        else
            return self:doerror(
                2,
                string.format(
                    'plugin upload usr is <%s>, dele must login <%s> first! not <%s>',
                    p_tar['gitee_usr'],
                    p_tar['gitee_usr'],
                    reqdata['usr']
                )
            )
        end
    end
    self:doerror(1, 'not find or delete failed')
end

--[[--
ccpm添加tool
]]
function _ccpm:post_addtool()
    local err, reqdata = self:get_body_params_()
    if err then
        self:doerror(err, 'decode error')
        return
    end
    local retchk = self:_chk_tool_dic(reqdata)
    if retchk then
        -- chk name
        local p_list = self._orm_ccpm:find_all_with_tbname(DB_GAMEDEV['tools'], {name = reqdata['name']})
        if type(p_list) == 'table' then
            for _, pinfo in ipairs(p_list) do
                if pinfo['ver'] == reqdata['ver'] then
                    self:doerror(2, 'tools exists!')
                    return
                end
            end
        end
        reqdata['uploadtime'] = ngx.time()
        local ret = self._orm_ccpm:new_insert_with_tbname(DB_GAMEDEV['tools'], reqdata)
        d.Logger:info('insert db->>>ret %s', tostring(ret))
        if ret then
            self:doret(0)
        else
            self:doerror(1, 'inser failed')
        end
    else
        self:doerror(1, 'insert info fmt not right')
    end
end

--[[--
ccpm确认列表数据
]]
function _ccpm:get_pageidxinfo()
    local reqdata = ngx.req.get_uri_args() or {}
    local ltype = reqdata['ltype'] == 'tools' and 1 or 0
    local tb_name = ltype == 0 and DB_GAMEDEV['plugins'] or DB_GAMEDEV['tools']
    local pageidx = reqdata['pageidx'] or 1
    local pagecnt = reqdata['pagecnt'] or 1000
    local ret = self._orm_ccpm:get_limitcnt_with_tbname(tb_name, pagecnt * (pageidx - 1), pagecnt * pageidx)
    if type(ret) == 'table' then
        self:doret(ret)
    else
        self:doalert('DB', 2)
    end
end

function _ccpm:get_pageinfo_by_ptype()
    local ok, reqdata =
        self:url_jsonparams_nec_(
        {
            'staridx',
            'ptype', --插件大类
            'pagecnt'
        }
    )
    if not ok then
        return
    end
    local retcode = 0
    local pageidx = reqdata['staridx'] or 1
    local pagecnt = reqdata['pagecnt'] or 1000
    local plist =
        self._orm_ccpm:group_name_by_limitcond({ptype = tonumber(reqdata['ptype'])}, reqdata['staridx'], reqdata['pagecnt'])
    if plist then
        self:doret(plist)
    else
        self:doalert('DB', 2)
    end
end

function _ccpm:get_plugin_grouupby_name()
    local ok, reqdata = self:url_jsonparams_nec_()
    if not ok then
        return
    end
end

function _ccpm:get_plugininfo()
    local ok, reqdata =
        self:url_jsonparams_nec_(
        {
            "cond"
        }
    )
    if not ok then
        return
    end
    local retcode = 0
    local cmd_dic= {}
    try {
        function()
            cmd_dic = json.decode(reqdata['cond'])
        end,
        catch {
            function(err)
                Logger:error("json decode error!")
            end
        }
    }

    local plist = self._orm_ccpm:find_all(cmd_dic)
    if plist then
        self:doret(plist)
    else
        self:doalert('DB', 2)
    end
end

function _ccpm:post_addplugin_fav()
    local ok, reqdata = self:body_jsonparams_nec_({
        "id",
        "name", 
        "desc", 
    })
    if not ok then
        return
    end
    local ret = self._orm_ccpmafav:new_insert(
        reqdata["id"],
        reqdata["name"],
        reqdata["desc"]
    )
    print(ret, '-->>>ret')
end
--==========================================================================
--一下是实现所需私有方法
--==========================================================================

function _ccpm:_chk_xlmake_update(cont)
    local ERR_PARAM = 'send param raise error'
    if not cont then
        return false, ERR_PARAM
    end
    if cont['sign'] == '123!@#xlmake' then
        local tar = require('cfg.cfgbinchk')
        d.Logger:info('---base ver%d,  comp ver %d', tar['int_ver'], _fmt_binver(cont['strver']))
        if tar['int_ver'] <= _fmt_binver(cont['strver']) then
            return true
        else
            return false, tar['desc']
        end
    end
    return false, ERR_PARAM
end

function _ccpm:_chk_plugin_dic(cont)
    local db_fmt = {
        name = 1,
        ver = 1,
        desc = 1,
        entry = 1,
        license = 1,
        dependencies = 1,
        md5 = 1,
        uploadtime = 1,
        contsize = 1,
        gitee_usr = 1,
        ptype = 1
    }
    for k, v in pairs(cont) do
        if not db_fmt[k] then
            cont[k] = nil
        end
    end
    return true
end

function _ccpm:_chk_tool_dic(cont)
    local db_fmt = {
        name = 1,
        ver = 1,
        desc = 1,
        license = 1,
        contsize = 1,
        uploadtime = 1,
        md5 = 1,
        gitee_usr = 1,
        filename = 1, 
        ptype = 1
    }
    for k, v in pairs(cont) do
        if not db_fmt[k] then
            cont[k] = nil
        end
    end
    return true
end

return _ccpm
